#include <dspSimulator/instruction/lmbd.h>


bool LMBD::checkCondition(std::shared_ptr<DspMachine> dspMachine) {
    return checkStandardCondition(dspMachine);
}

void LMBD::loadInstIRIntoJit(llvm::LLVMContext *llvmContext, llvm::Module *module,
                             std::shared_ptr<llvm::IRBuilder<>> irBuilder) {

}

std::shared_ptr<Instruction> LMBD::decode(std::shared_ptr<InstInfo> instInfo, u64 baseCycle) {
    std::shared_ptr<LMBD> lmbd;
    auto dspInstInfo = std::dynamic_pointer_cast<DspInstInfo>(instInfo);
    bool isStandardInst = dspInstInfo->isStandardInstruction();
    if (isStandardInst) {
        auto data = vectorToBitSet<32>(dspInstInfo->getBits());
        if (checkBits<10>(data, 2, 0b1101011110) && existStandardCondition(data)) {

        } else if (checkBits<10>(data, 2, 0b1101010110) && existStandardCondition(data)) {
            lmbd = std::make_shared<LMBD>(dspInstInfo->getAddress(), baseCycle);
            lmbd->creg_z = extractBits<4>(data, 28);
            lmbd->dst = extractBits<5>(data, 23).to_ulong();
            lmbd->src2 = extractBits<5>(data, 18).to_ulong();
            lmbd->cst = extractBits<5>(data, 13).to_ulong();
            lmbd->x = data[12];
            lmbd->s = data[1];
            lmbd->p = data[0];
            if (lmbd->s == 0) {
                lmbd->funcUnit = FuncUnit::L1;
            } else {
                lmbd->funcUnit = FuncUnit::L2;
            }
            lmbd->instFormat = InstFormat::Kind2;
        }
    }
    return lmbd;
}

void LMBD::executeCustom(std::shared_ptr<TargetMachine> targetMachine, ExecutePhase executePhase) {
    int res = 0;
    if (instFormat == InstFormat::Kind2) {
        std::bitset<32> data = *src2LoRegPtr;
        for (i32 i = 31; i >= 0; i--) {
            if (data[i] == cst) {
                break;
            } else {
                res++;
            }
        }
        *dstLoRegPtr = res;
    }
}

std::string LMBD::toString() const {
    std::string res;
    if (!isCompactInstruction) {
        res += getStandardConditionString() + " ";
    }
    res += m_name + " " + FuncUnitName[static_cast<u32>(funcUnit)] + " ";
    if (instFormat == InstFormat::Kind2) {
        res += getSrc1Reg32Name() + "," + getSrc2Reg32Name() + "," + getDstReg32Name();
    }
    return res;
}

std::shared_ptr<DspInstruction> LMBD::clone() {
    return std::make_shared<LMBD>(*this);
}
